home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Online / SpeakFreely / src / reflect.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  43KB  |  1,444 lines

  1. /*
  2.  
  3.             Speak Freely for Unix
  4.              Conference Reflector
  5.  
  6.       Designed and implemented in April of 1998 by John Walker.
  7.  
  8.     Note: this reflector currently works by simple packet replication;
  9.     it does not examine the contents of packets or attempt to merge
  10.     arriving audio streams in any intelligent fashion.    Because it
  11.     appears to a connected user as a single connection in Speak
  12.     Freely protocol, users must connect in Speak Freely protocol
  13.     in order for their audio to be successfully decoded by others.
  14.     I've left in complete logic for VAT and RTP connections,
  15.     however, in order to make it easier to support those protocols
  16.     if, in the future, the reflector is extended to add additional
  17.     reflector and/or mixer functionality.
  18.  
  19. */
  20.  
  21. #include "speakfree.h"
  22. #include "version.h"
  23. #include "vat.h"
  24.  
  25. #define SHOW_SOCKET
  26.  
  27. #define Reflect_Base 2000          /* Reflector offset from default speaker port */
  28.  
  29. static int debugforce = 0;          /* Debugging forced / prevented ? */
  30. static int whichport = Internet_Port + Reflect_Base; /* Port to listen on (base address) */
  31. static int sock;              /* Input socket */
  32. static int ssock;              /* Control socket (RTP/VAT) */
  33. static struct sockaddr_in from;       /* Sending host address */
  34. static struct sockaddr_in name;       /* Address of destination host */
  35. static int fromlen;              /* Length of sending host address */
  36. static int showhosts = FALSE;          /* Show host names that connect */
  37. static int hosttimeout = 180;          /* Consider host idle after this number of seconds */
  38. static char *prog;              /* Program name */ 
  39.  
  40. static struct sockaddr_in lookhost;   /* Look who's listening host, if any */
  41. static char *sdes = NULL;          /* RTP SDES packet */
  42. static int sdesl;              /* RTP SDES packet length */
  43. static unsigned long ssrc;          /* RTP synchronisation source identifier */
  44. static long lwltimer;              /* Time next LWL retransmit scheduled */
  45. static int actives = 0;           /* Currently active hosts */
  46.  
  47. #define LWL_RETRANSMIT    (5 * 60)      /* Seconds between LWL updates */
  48.  
  49. static struct in_addr lwl_sites[LWL_MAX_SITES]; /* LWL site addresses */
  50. static int lwl_ports[LWL_MAX_SITES];  /* Ports for LWL hosts */
  51. static int lwl_nsites = 0;          /* Number of LWL sites published on */
  52.  
  53. static int monitor = 0;           /* Audio monitor ? */
  54. static struct in_addr monitor_site;   /* Audio monitor site */
  55. static int monitor_port;          /* Audio monitor port */
  56.  
  57. static struct in_addr local_site;     /* IP address running reflector */
  58. static int local_site_known = 0;      /* Nonzero if local IP address known */
  59. #ifndef INADDR_LOOPBACK           /* Should be defined in netinet/in.h, but just in case */
  60. #define INADDR_LOOPBACK (unsigned long) 0x7F000001L
  61. #endif
  62.  
  63. static char *htmlFile = NULL;          /* HTML file name base */
  64. static int htmlTime = 1 * 60;          /* HTML file update time */
  65. static time_t htmlLast = 0;          /* HTML last update time */
  66. static int htmlChange = TRUE;          /* Change since last HTML update ? */
  67. static int htmlRefresh = 0;          /* HTML client-pull refresh interval */
  68. #define HTML_REFRESH    "<meta http-equiv=\"Refresh\" content=\"%d\">\n"
  69.  
  70. #define connection r_connection
  71.  
  72. /* Open connection state. */
  73.  
  74. struct connection {
  75.     struct connection *con_next;      /* Next connection */
  76.     struct in_addr con_addr;          /* Host Internet address */
  77.     long con_timeout;              /* Connection timeout */
  78.     char con_hostname[264];          /* Host name */
  79.     short con_protocol;           /* Transmission protocol */
  80.     char con_session[4];          /* VAT/RTP session identifier */
  81.  
  82.     char con_uname[4096];          /* User name */
  83.     char con_email[256];          /* User E-mail address, if known */
  84.  
  85.     /* Special fields for reflector. */
  86.  
  87.     char *con_compmodes;          /* Last compression modes */
  88.     int con_control;              /* Control packet seen ? */
  89.     int con_bye;              /* BYE packet received ? */
  90.  
  91.     char con_cname[256];          /* RTCP unique name identifier */
  92.     char con_phone[256];          /* User phone number */
  93.     char con_loc[1024];           /* User location */
  94.     time_t con_ltime;              /* Last update time */
  95. };
  96.  
  97. static struct connection *conn = NULL; /* Chain of current connections */
  98.  
  99. #define Debug        (debugforce != 0) /* Generate debug output */
  100.  
  101. #define TickTock    7              /* Alarm interval in seconds */
  102. #define TockTock    60              /* Alarm interval when no connections open */
  103.  
  104. static int crit = FALSE;          /* Queue critical section lock */
  105. static int clash = FALSE;          /* Critical section clash retry flag */
  106.  
  107. /*  ETIME  --  Edit time and date for log messages.  */
  108.  
  109. static char *etime(gmt)
  110.   int gmt;
  111. {
  112.     struct tm *t;
  113.     time_t clock;
  114.     static char s[20];
  115.  
  116.     time(&clock);
  117.     if (gmt) {
  118.     t = gmtime(&clock);
  119.     } else {
  120.     t = localtime(&clock);
  121.     }
  122.     sprintf(s, "%d-%02d-%02d %02d:%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
  123.            t->tm_hour, t->tm_min);
  124.     return s;
  125. }
  126.  
  127. /*  COMPRESSIONTYPE  --  Return a string describing the type of
  128.              compression employed in this buffer.  We
  129.              attempt to distinguish RTP and VAT
  130.                          messages from our own here.  This isn't
  131.              100% reliable in the case of VAT, but
  132.              nothing really terrible will happen if
  133.              we guess wrong.  We only test a packet for
  134.                          VAT if given the clue that we've seen a
  135.              packet arrive on the control channel. */
  136.  
  137. static char *compressionType(msg, clue)
  138.   soundbuf *msg;
  139.   int clue;
  140. {
  141.     unsigned char *p = (unsigned char *) msg;
  142.  
  143.     if (((p[0] >> 6) & 3) == RTP_VERSION) {
  144.     char *r;
  145.  
  146.     switch (p[1] & 0x7F) {
  147.         case 0:
  148.                 r = "RTP PCMU";
  149.         break;
  150.  
  151.         case 1:
  152.                 r = "RTP 1016";
  153.         break;
  154.  
  155.         case 2:
  156.                 r = "RTP G721";
  157.         break;
  158.  
  159.         case 3:
  160.                 r = "RTP GSM";
  161.         break;
  162.  
  163.         case 5:
  164.         case 6:
  165.                 r = "RTP DVI4";
  166.         break;
  167.  
  168.         case 7:
  169.                 r = "RTP LPC";
  170.         break;
  171.  
  172.         case 8:
  173.                 r = "RTP PCMA";
  174.         break;
  175.  
  176.         case 9:
  177.                 r = "RTP G722";
  178.         break;
  179.  
  180.         case 10:
  181.         case 11:
  182.                 r = "RTP L16";
  183.         break;
  184.  
  185.         default:
  186.                 r = "RTP Unknown";
  187.         break;
  188.     }
  189.     return r;
  190.     }
  191.  
  192.     /* Hokey attempt to detect VAT packets.  We can't tell
  193.        VAT PCMU packets from unmarked Speak Freely packets, so
  194.        we let them fall through. */
  195.  
  196.     if (clue && (p[0] & 0xC0) == 0) {
  197.     char *r = NULL;
  198.  
  199.     switch (p[1] & 0x7F) {
  200.         case VAT_AUDF_GSM:
  201.                 r = "VAT GSM";
  202.         break;
  203.  
  204.         case VAT_AUDF_LPC4:
  205.                 r = "VAT LPC";
  206.         break;
  207.  
  208.         case VAT_AUDF_IDVI:
  209.                 r = "VAT IDVI";
  210.         break;
  211.  
  212.         case VAT_AUDF_L16_16:
  213.         case VAT_AUDF_L16_44:
  214.                 r = "VAT L16";
  215.         break;
  216.     }
  217.     if (r != NULL) {
  218.         return r;
  219.     }
  220.     }
  221.  
  222.     return ((msg->compression & (fComp2X | fCompGSM)) ==
  223.                 (fComp2X | fCompGSM)) ?
  224.                                 "GSM+2X compressed" :
  225.        ((msg->compression & (fComp2X | fCompADPCM)) ==
  226.                 (fComp2X | fCompADPCM)) ?
  227.                                 "ADPCM+2X compressed" :
  228.        ((msg->compression & (fComp2X | fCompLPC)) ==
  229.                 (fComp2X | fCompLPC)) ?
  230.                                 "LPC+2X compressed" :
  231.        ((msg->compression & (fComp2X | fCompLPC10)) ==
  232.                 (fComp2X | fCompLPC10)) ?
  233.                                 "LPC10+2X compressed" :
  234.        ((msg->compression & (fComp2X | fCompVOX)) ==
  235.                 (fComp2X | fCompVOX)) ?
  236.                                 "VOX+2X compressed" :
  237.            ((msg->compression & fCompADPCM) ? "ADPCM compressed" :
  238.            ((msg->compression & fCompLPC) ? "LPC compressed" :
  239.            ((msg->compression & fCompLPC10) ? "LPC10 compressed" :
  240.            ((msg->compression & fComp2X) ? "2X compressed" :
  241.            ((msg->compression & fCompGSM) ? "GSM compressed" :
  242.            ((msg->compression & fCompVOX) ? "VOX compressed" :
  243.                                             "uncompressed"))))));
  244. }
  245.  
  246. /*  MAKESESSIONKEY  --    Generate session key.  */
  247.  
  248. static void makeSessionKey(key)
  249.   char *key;
  250. {
  251.     struct MD5Context md5c;
  252.     char s[1024];
  253.  
  254.     s[0] = 0;
  255.  
  256.     /* If you get compile or link errors on references to any of the
  257.        following functions, simply comment out the offending lines and
  258.        try again.  This sequence of code uses a variety of information
  259.        about the instantaneous execution environment of the program to
  260.        construct a unique session key (or SSRC) to uniquely identify
  261.        this sender in RTP packets.  The intent is to stir as many
  262.        items into the cauldron as possible so that the resulting brew,
  263.        cranked through MD5, will have as close a probability as
  264.        possible to 1 in 2^32 of duplicating that of another user.
  265.        Note that RTP does not guarantee SSRCs are unique.  If a
  266.        duplication should occur, the result may be confusing but not
  267.        disastrous.  */
  268.  
  269.     sprintf(s + strlen(s), "%u", getpid());
  270.     sprintf(s + strlen(s), "%u", getppid());
  271.     V getcwd(s + strlen(s), 256);
  272.     sprintf(s + strlen(s), "%lu", clock());
  273.     V cuserid(s + strlen(s));
  274.     sprintf(s + strlen(s), "%lu", time(NULL));
  275. #ifdef Solaris
  276.     sysinfo(SI_HW_SERIAL, s + strlen(s), 12);
  277. #else
  278.     sprintf(s + strlen(s), "%u", gethostid());
  279. #endif
  280.     getdomainname(s + strlen(s), 256);
  281.     gethostname(s + strlen(s), 256);
  282.     sprintf(s + strlen(s), "%u", getuid());
  283.     sprintf(s + strlen(s), "%u", getgid());
  284.     MD5Init(&md5c);
  285.     MD5Update(&md5c, s, strlen(s));
  286.     MD5Final(key, &md5c);
  287. }
  288.  
  289. /*  SENDLWLMESSAGE  --    If enabled, send a message identifying us
  290.                         to each selected Look Who's Listening server.  */
  291.  
  292. static void sendLwlMessage(dobye)
  293.   int dobye;
  294. {
  295.     int i, sock;
  296.  
  297.     for (i = 0; i < lwl_nsites; i++) {
  298.     if (lwl_ports[i] >= 0) {
  299.         sock = socket(AF_INET, SOCK_STREAM, 0);
  300.         if (sock < 0) {
  301.                 perror("opening look who's listening socket");
  302.         sdes = NULL;
  303.         return;
  304.         }
  305.  
  306.         lookhost.sin_port = htons(lwl_ports[i]);
  307.         bcopy((char *) (&lwl_sites[i]), (char *) &lookhost.sin_addr.s_addr,
  308.           sizeof lookhost.sin_addr.s_addr);
  309.  
  310.         if (connect(sock, (struct sockaddr *) &(lookhost), sizeof lookhost) >= 0) {
  311.         if (dobye) {
  312.             char v[1024];
  313.             int l;
  314.  
  315.                     l = rtp_make_bye(v, ssrc, "Exiting sfreflect", FALSE);
  316.             if (send(sock, v, l, 0) < 0) {
  317.                         perror("sending look who's listening BYE packet");
  318.             }
  319.             if (Debug) {
  320.                         fprintf(stderr, "%s: sent LWL BYE message to %s/%d.\n", prog,
  321.                 inet_ntoa(lwl_sites[i]), lwl_ports[i]);
  322.             }
  323.         } else {
  324.             if (send(sock, (char *) sdes, sdesl, 0) < 0) {
  325.                         perror("sending look who's listening source ID message");
  326.             }
  327.             if (Debug) {
  328.                         fprintf(stderr, "%s: sent LWL message to %s/%d.\n", prog,
  329.                 inet_ntoa(lwl_sites[i]), lwl_ports[i]);
  330.             }
  331.         }
  332.         } else {
  333.                 perror("connecting look who's listening socket");
  334.         }
  335.     }
  336.     }
  337.     lwltimer = LWL_RETRANSMIT;
  338.     close(sock);
  339. }
  340.  
  341. /*  MAKEHTML  --  Create an HTML file showing current connections.  If
  342.                   "private" is set, exact-match names are included
  343.           in the HTML file.  */
  344.  
  345. static void makeHTML(fname, private)
  346.   char *fname;
  347.   int private;
  348. {
  349.     FILE *of;
  350.     char f[132], fn[132];
  351.  
  352.     strcpy(f, fname);
  353.     strcat(f, ".new");
  354.     of = fopen(f, "w");
  355.     if (of != NULL) {
  356.     struct connection *lw;
  357.  
  358. #define P(x) fprintf(of, x)
  359.  
  360.     lw = conn;
  361.         P("<html>\n<head>\n");
  362.     if (htmlRefresh > 0) {
  363.         fprintf(of, HTML_REFRESH, htmlRefresh);
  364.     }
  365.         P("<title>\nSpeak Freely: Sites Active on Reflector\n");
  366.         P("</title>\n</head>\n\n<body>\n<center>\n<h1>");
  367.         P("Speak Freely: Sites Active on Reflector</h1>\n<h2>");
  368.         fprintf(of, "Last change: %s UTC</h2>\n</center>\n<p>\n", etime(TRUE));
  369.  
  370.     if (lw == NULL) {
  371.             P("<h2>No sites active.</h2>\n");
  372.     } else {
  373.         int i = 0;
  374.  
  375.         while (lw != NULL) {
  376.                 if (!lw->con_bye && (private || ((lw->con_email[0] != '*') &&
  377.                     (lw->con_cname[0] != '*')))) {
  378.             i++;
  379.         }
  380.         lw = lw->con_next;
  381.         }
  382.         lw = conn;
  383.         if (i == 0) {
  384.         /* Fib about number of sites active if all active sites
  385.                    don't want a directory listing or are in termination. */
  386.                 P("<h2>No sites active.</h2>\n");
  387.         } else {
  388.                 fprintf(of, "<h2>%d site%s active.</h2>\n",
  389.                     i, i == 1 ? "" : "s");
  390.                 P("<pre>\n");
  391.         while (lw != NULL) {
  392.                     if (!lw->con_bye && (private || ((lw->con_email[0] != '*') &&
  393.                         (lw->con_cname[0] != '*')))) {
  394.             char ipport[40];
  395.             struct tm *lt;
  396.             char s[384];
  397.  
  398.             lt = gmtime(&lw->con_ltime);
  399.                         sprintf(ipport, "%s:%d", inet_ntoa(lw->con_addr), whichport);
  400.                         sprintf(s, "\n%-24s %-48s %02d:%02d\n", ipport, lw->con_cname,
  401.                 lt->tm_hour, lt->tm_min);
  402.             outHTML(of, s);
  403.             if (lw->con_uname[0] != 0) {
  404.                             sprintf(s, "%25s%s\n", "", lw->con_uname);
  405.                 outHTML(of, s);
  406.             }
  407.             if (lw->con_loc[0] != 0) {
  408.                             sprintf(s, "%25s%s\n", "", lw->con_loc);
  409.                 outHTML(of, s);
  410.             }
  411.             if (lw->con_phone[0] != 0) {
  412.                             sprintf(s, "%25sPhone:  %s\n", "", lw->con_phone);
  413.                 outHTML(of, s);
  414.             }
  415.             if (lw->con_email[0] != 0) {
  416.                             sprintf(s, "%25sE-mail: %s\n", "", lw->con_email);
  417.                 outHTML(of, s);
  418.             }
  419.             }
  420.             lw = lw->con_next;
  421.         }
  422.                 P("</pre>\n");
  423.         }
  424.     }
  425.  
  426.         P("</body>\n</html>\n");
  427.     fclose(of);
  428.     strcpy(fn, fname);
  429.         strcat(fn, ".html");
  430.     rename(f, fn);
  431.     if (Debug) {
  432.             fprintf(stderr, "%s: updated %s\n", prog, fn);
  433.     }
  434.     }
  435. }
  436.  
  437. /*  UPDHTML  --  Update HTML if necessary.  */
  438.  
  439. static void updHTML()
  440. {
  441.     time_t now;
  442.  
  443.     if ((htmlFile != NULL) && htmlChange && 
  444.     ((htmlTime <= 0) || (((now = time(NULL)) - htmlLast) > htmlTime))) {
  445.     htmlLast = now;
  446.     htmlChange = FALSE;
  447.     if (htmlFile != NULL) {
  448.         /* The reflector always includes names of connected users
  449.                in its HTML summary, even if they've flagged their
  450.                names not to appear in sflwld's public HTML output.
  451.            The logic is that connecting to a reflector is
  452.            equivalent to connecting to another user, in which
  453.                case one's identity is shown.  If you want to permit
  454.                "stealth conference members", change the TRUE in the
  455.            following line to FALSE. */
  456.         makeHTML(htmlFile, TRUE);
  457.     }
  458.     }
  459. }
  460.  
  461. /*  CHANGED  --  Indicate a change which may require updating
  462.          the HTML file.  */
  463.  
  464. static void changed()
  465. {
  466.     htmlChange = TRUE;
  467.     updHTML();
  468. }
  469.  
  470. /*  RELEASE  --  Alarm signal-catching function to retransmit
  471.          packets at the correct time and to time out
  472.          idle hosts.  */
  473.  
  474. static void release()
  475. {
  476.     struct connection *c, *l, *n;
  477.  
  478.     if (crit) {
  479.     clash = TRUE;
  480.     alarm(60);
  481.     if (Debug) {
  482.             fprintf(stderr, "%s: Critical section clash in release()\n", prog);
  483.     }
  484.     } else {
  485.     int timerStep;
  486.     long tdate;
  487.     char *hdes = NULL;
  488.     int hdesl;
  489.  
  490.     time(&tdate);
  491.  
  492.     /* Mark idle any hosts that have sent us a BYE message or
  493.            haven't sent any packets in the last hosttimeout seconds. */
  494.  
  495.     c = conn;
  496.     l = NULL;
  497.     actives = 0;
  498.     while (c != NULL) {
  499.         n = c->con_next;
  500.         if (!c->con_bye && (tdate < (c->con_timeout + hosttimeout))) {
  501.         actives++;
  502.         l = c;
  503.         if (Debug) {
  504.                     fprintf(stderr, "Host %s %ld seconds from timeout.\n",
  505.             c->con_hostname, (c->con_timeout + hosttimeout) - tdate);
  506.         }
  507.         } else {
  508.         if (showhosts) {
  509.                     fprintf(stderr, "%s: %s %s idle\n", prog, etime(FALSE), c->con_hostname);
  510.         }
  511.         if (l == NULL) {
  512.             conn = n;
  513.         } else {
  514.             l->con_next = n;
  515.         }
  516.         free(c);
  517.         htmlChange = TRUE;    /* Indicate HTML file update needed */
  518.         }
  519.         c = n;
  520.     }
  521.  
  522.         /* Update our Look Who's Listening information if the
  523.        timeout has expired. */
  524.  
  525.     if (sdes != NULL && tdate >= lwltimer) {
  526.         sendLwlMessage(FALSE);
  527.         lwltimer = tdate + LWL_RETRANSMIT;
  528.     }
  529.  
  530.     /* If any hosts are active, send them all a heartbeat
  531.        identifying the reflector. */
  532.  
  533.     if (actives > 0) {
  534.         struct connection *rc;
  535.  
  536.         hdesl = rtp_make_sdes(&hdes, ssrc, -1, TRUE);
  537.         /* Set Speak Freely protocol flag in packet */
  538.         hdes[0] = (hdes[0] & 0x3F) | (1 << 6);
  539.         rc = conn;
  540.         while (rc != NULL) {
  541.  
  542.         /* Once again we have to worry about the case where the
  543.            reflector is being accessed from the same machine on
  544.                    which it is running.  In that case, we'll have a 
  545.            connection in the chain for the local host, since sfmike
  546.                    is sending us heartbeats and sound, but we don't want
  547.                    to send heartbeats since they'd loop right back and
  548.            wind up in our own input queue.  So, test the address
  549.                    against the local site and skip the heartbeat if they're
  550.            the same.  The actual heartbeats to the copy of sfspeaker
  551.            on the local host are sent in the section of code below
  552.            which deals with the monitoring host. */
  553.  
  554.         if (!rc->con_bye &&
  555.             (ntohl(rc->con_addr.s_addr) != INADDR_LOOPBACK) &&
  556.             (!local_site_known ||
  557.              (memcmp(&local_site, &(rc->con_addr), sizeof(struct in_addr)) != 0))) {
  558.             struct sockaddr_in pto;
  559.  
  560.             pto.sin_family = AF_INET;
  561.             pto.sin_port = htons(whichport + 1);
  562.             bcopy(&(rc->con_addr), &pto.sin_addr, sizeof(struct in_addr));
  563.             if (sendto(sock, hdes, hdesl,
  564.             0, (struct sockaddr *) &pto,
  565.             sizeof(struct sockaddr_in)) < 0) {
  566.                         perror("sending heartbeat");
  567.             }
  568.             if (Debug) {
  569.                         fprintf(stderr, "%s: sending heartbeat to %s/%d (%s).\n",
  570.                 prog, inet_ntoa(rc->con_addr),
  571.                 whichport + 1, rc->con_hostname);
  572.             }
  573.         }
  574.         rc = rc->con_next;
  575.         }
  576.     }
  577.  
  578.     /* If there is a monitor host, send it a heartbeat also.  */
  579.  
  580.     if (monitor) {
  581.         struct sockaddr_in pto;
  582.  
  583.         if (hdes == NULL) {
  584.         hdesl = rtp_make_sdes(&hdes, ssrc, -1, TRUE);
  585.         /* Set Speak Freely protocol flag in packet */
  586.         hdes[0] = (hdes[0] & 0x3F) | (1 << 6);
  587.         }
  588.  
  589.         pto.sin_family = AF_INET;
  590.         pto.sin_port = htons(monitor_port + 1);
  591.         bcopy(&(monitor_site), &pto.sin_addr, sizeof(struct in_addr));
  592.         if (sendto(sock, hdes, hdesl,
  593.         0, (struct sockaddr *) &pto,
  594.         sizeof(struct sockaddr_in)) < 0) {
  595.                 perror("sending heartbeat");
  596.         }
  597.         if (Debug) {
  598.                 fprintf(stderr, "%s: sending heartbeat to monitor host %s/%d.\n",
  599.             prog, inet_ntoa(monitor_site),
  600.             monitor_port + 1);
  601.         }
  602.     }
  603.     if (hdes != NULL) {
  604.         free(hdes);
  605.     }
  606.  
  607.     /* Reset the timer based on whether anybody is active. */
  608.  
  609.     if (actives > 0) {
  610.         timerStep = TickTock;
  611.     } else {
  612.         timerStep = TockTock;
  613.     }
  614.     alarm(timerStep);
  615.     if (Debug) {
  616.         time_t t;
  617.         struct tm *ltd;
  618.  
  619.         time(&t);
  620.         ltd = localtime(&t);
  621.             fprintf(stderr, "Tick: %2d:%02d %d...\n", ltd->tm_hour, ltd->tm_min, timerStep);
  622.     }
  623.     }
  624.     updHTML();                        /* Update HTML if something's changed recently */
  625.     signal(SIGALRM, release);          /* Reset signal to handle timeout */
  626. }
  627.  
  628. /*  EXITING  --  Catch as many program termination signals as
  629.          possible and clean up before exit.  */
  630.  
  631. static void exiting()
  632. {
  633.     if (sdes) {
  634.     /* De-list from LWL server. */
  635.     sendLwlMessage(TRUE);
  636.     }
  637.     exit(0);
  638. }
  639.  
  640. /*  PROG_NAME  --  Extract program name from argv[0].  */
  641.  
  642. static char *prog_name(arg)
  643.   char *arg;
  644. {
  645.     char *cp = strrchr(arg, '/');
  646.  
  647.     return (cp != NULL) ? cp + 1 : arg;
  648. }
  649.  
  650. /*  USAGE  --  Print how-to-call information.  */
  651.  
  652. static void usage()
  653. {
  654.     V fprintf(stderr, "%s  --  Speak Freely conference reflector.\n", prog);
  655.     V fprintf(stderr, "               %s.\n", Relno);
  656.     V fprintf(stderr, "\n");
  657.     V fprintf(stderr, "Usage: %s [options]\n", prog);
  658.     V fprintf(stderr, "Options:\n");
  659.     V fprintf(stderr, "           -D               Enable debug output\n");
  660.     V fprintf(stderr, "           -Hpath           Write HTML active site list on base path\n");
  661.     V fprintf(stderr, "           -Insec           Interval between HTML updates\n");
  662.     V fprintf(stderr, "           -Mhost[:port]    Monitor audio on host and port\n");
  663.     V fprintf(stderr, "           -Pport           Listen on given port\n");
  664.     V fprintf(stderr, "           -Rnsec           Client-pull HTML refresh every nsec seconds\n");
  665.     V fprintf(stderr, "           -U               Print this message\n");
  666.     V fprintf(stderr, "           -Vtimeout        Show hostnames that connect\n");
  667.     V fprintf(stderr, "\n");
  668.     V fprintf(stderr, "by John Walker\n");
  669.     V fprintf(stderr, "   http://www.fourmilab.ch/\n");
  670. }
  671.  
  672. /*  Main program.  */
  673.  
  674. main(argc, argv)
  675.   int argc;
  676.   char *argv[];
  677. {
  678.     int i, length;
  679.     struct soundbuf sb;
  680.     struct connection *c;
  681.     char *cp;
  682.     int newconn;
  683.     char md5key[16];
  684.  
  685.     prog = prog_name(argv[0]);
  686.  
  687.     /* First pass option processing.  We have to first scan
  688.        the options to handle any which affect creation of the
  689.        socket.    */
  690.  
  691.     for (i = 1; i < argc; i++) {
  692.     char *op, opt;
  693.  
  694.     op = argv[i];
  695.         if (*op == '-') {
  696.         opt = *(++op);
  697.         if (islower(opt)) {
  698.         opt = toupper(opt);
  699.         }
  700.  
  701.         switch (opt) {
  702.  
  703.                 case 'P':             /* -Pport  --  Port to listen on */
  704.             whichport = atoi(op + 1);
  705.             break;
  706.  
  707.                 case 'U':             /* -U  --  Print usage information */
  708.                 case '?':             /* -?  --  Print usage information */
  709.             usage();
  710.             return 0;
  711.         }
  712.     } else {
  713.         usage();
  714.         return 2;
  715.     }
  716.     }
  717.  
  718.     /* Create the sockets from which to read audio and control packets. */
  719.  
  720.     sock = socket(AF_INET, SOCK_DGRAM, 0);
  721.     if (sock < 0) {
  722.         perror("opening data socket");
  723.     return 1;
  724.     }
  725.  
  726.     ssock = socket(AF_INET, SOCK_DGRAM, 0);
  727.     if (ssock < 0) {
  728.         perror("opening control socket");
  729.     return 1;
  730.     }
  731.  
  732.     /* Create name with wildcards. */
  733.  
  734.     name.sin_family = AF_INET;
  735.     name.sin_addr.s_addr = INADDR_ANY;
  736.     name.sin_port = htons(whichport);
  737.     if (bind(sock, (struct sockaddr *) &name, sizeof name) < 0) {
  738.         perror("binding data socket");
  739.     return 1;
  740.     }
  741.     name.sin_port = htons(whichport + 1);
  742.     if (bind(ssock, (struct sockaddr *) &name, sizeof name) < 0) {
  743.         perror("binding control socket");
  744.     return 1;
  745.     }
  746.     name.sin_port = htons(whichport);
  747.  
  748.     for (i = 1; i < argc; i++) {
  749.     char *op, opt;
  750.  
  751.     op = argv[i];
  752.         if (*op == '-') {
  753.         opt = *(++op);
  754.         if (islower(opt)) {
  755.         opt = toupper(opt);
  756.         }
  757.  
  758.         switch (opt) {
  759.  
  760.                 case 'D':             /* -D  --  Force debug output */
  761.             debugforce = 1;
  762.             break;
  763.  
  764.                 case 'H':             /* -Hname  --  HTML file name base path */
  765.             htmlFile = op + 1;
  766.             break;
  767.  
  768.                 case 'I':             /* -Isec  --  Interval between HTML updates */
  769.             htmlTime = atoi(op + 1);
  770.             break;
  771.  
  772.                 case 'M':             /* -Mhost:port  --  Monitor on given host and port */
  773.             {
  774.             char *ep, *cp = op + 1;
  775.             long iadr;
  776.             struct hostent *h;
  777.  
  778.             monitor_port = Internet_Port;
  779.                         if ((ep = strchr(cp, ':')) != NULL || (ep = strchr(cp, '/')) != NULL) {
  780.                 *ep = 0;
  781.                 monitor_port = atoi(ep + 1);
  782.             }
  783.             if (isdigit(*cp) && (iadr = inet_addr(cp)) != -1) {
  784.                 bcopy((char *) &iadr, (char *) (&monitor_site),
  785.                   sizeof iadr);
  786.                 monitor = 1;
  787.             } else {
  788.                 h = gethostbyname(cp);
  789.                 if (h != NULL) {
  790.                 bcopy((char *) (h->h_addr), 
  791.                       (char *) (&monitor_site),
  792.                       sizeof(unsigned long));
  793.                 monitor = 1;
  794.                 } else {
  795.                                 fprintf(stderr, "%s: warning, monitor host %s unknown.\n",
  796.                     prog, cp);
  797.                 }
  798.             }
  799.             if (Debug && monitor) {
  800.                             fprintf(stderr, "%s: sending monitor audio to %s/%d: %s.\n", prog,
  801.                 inet_ntoa(monitor_site), monitor_port, cp);
  802.             }
  803.             }
  804.             break;
  805.  
  806.                 case 'R':             /* -Rnsec  --  Interval between HTML client-pull updates */
  807.             htmlRefresh = atoi(op + 1);
  808.             break;
  809.  
  810.                 case 'V':             /* -V  --  Show hostnames that connect */
  811.             showhosts = TRUE;
  812.             if (op[1] != 0) {
  813.             int t = atoi(op + 1);
  814.  
  815.             if (t > 0) {
  816.                 if (t < (TickTock + 1)) {
  817.                 t = TickTock + 1;
  818.                 }
  819.                 hosttimeout = (t / TickTock) * TickTock;
  820.             }
  821.             }
  822.             break;
  823.         }
  824.     }
  825.     }
  826.  
  827.     /* Find assigned port value and print it. */
  828.  
  829.     length = sizeof(name);
  830.     if (getsockname(sock, (struct sockaddr *) &name, &length) < 0) {
  831.         perror("getting socket name");
  832.     return 1;
  833.     }
  834. #ifdef SHOW_SOCKET
  835.     fprintf(stderr, "%s: socket port #%d\n", prog, ntohs(name.sin_port));
  836. #endif
  837.  
  838.     /* Build the RTCP SDES packet identifying the reflector.
  839.        This packet is used both to identify the reflector to
  840.        those who connect and, if SPEAKFREE_LWL_TELL is defined,
  841.        to register the reflector with the designated look who's
  842.        listening hosts.  Note that we do *not* include a list
  843.        of the identities of currently-connected users in our
  844.        SDES, as a pure RTP reflector would do.    We rely instead
  845.        on an HTML file, which can be accessed by anybody with
  846.        a Web browser and does not require special support in
  847.        the audio client program. */
  848.  
  849.     makeSessionKey(md5key);
  850.     bcopy(md5key, (char *) &ssrc, sizeof ssrc);
  851.     sdesl = rtp_make_sdes(&sdes, ssrc, whichport, FALSE);
  852.  
  853.     /* Contact look who's listening host, if requested. */
  854.  
  855.     cp = getenv("SPEAKFREE_LWL_TELL");
  856.     if (cp != NULL) {
  857.     struct hostent *h;
  858.     char *ep, *np;
  859.     long iadr;
  860.     int n;
  861.  
  862.     lookhost.sin_family = AF_INET;
  863.  
  864.     while (lwl_nsites < LWL_MAX_SITES) {
  865.         n = lwl_nsites;
  866.         while (*cp != 0 && isspace(*cp)) {
  867.         cp++;
  868.         }
  869.         if (*cp == 0) {
  870.         break;
  871.         }
  872.             if ((np = strchr(cp, ',')) != NULL) {
  873.         *np++ = 0;
  874.         }
  875.         lwl_ports[lwl_nsites] = Internet_Port + 2;
  876.             if ((ep = strchr(cp, ':')) != NULL) {
  877.         *ep = 0;
  878.         lwl_ports[lwl_nsites] = atoi(ep + 1);
  879.         }
  880.         if (isdigit(*cp) && (iadr = inet_addr(cp)) != -1) {
  881.         bcopy((char *) &iadr, (char *) (&lwl_sites[lwl_nsites]),
  882.               sizeof iadr);
  883.         lwl_nsites++;
  884.         } else {
  885.         h = gethostbyname(cp);
  886.         if (h != NULL) {
  887.             bcopy((char *) (h->h_addr), 
  888.               (char *) (&lwl_sites[lwl_nsites]),
  889.               sizeof(unsigned long));
  890.             lwl_nsites++;
  891.         } else {
  892.                     fprintf(stderr, "%s: warning, SPEAKFREE_LWL_TELL host %s unknown.\n",
  893.             prog, cp);
  894.         }
  895.         }
  896.         if (Debug && lwl_nsites > n) {
  897.                 fprintf(stderr, "%s: publishing on LWL server %s: %s.\n", prog,
  898.             inet_ntoa(lwl_sites[n]), cp);
  899.         }
  900.         if (np == NULL) {
  901.         break;
  902.         }
  903.         cp = np;
  904.     }
  905.     if (lwl_nsites > 0) {
  906.         sendLwlMessage(FALSE);
  907.     }
  908.     }
  909.  
  910.     /* Determine the IP address of the host running the
  911.        reflector.  We need this to avoid duplicating packets
  912.        when the reflector is both running and being accessed
  913.        from the same machine. */
  914.  
  915.     {
  916.     struct hostent *h;
  917.     char hname[256];
  918.  
  919.     if (gethostname(hname, sizeof hname) == 0) {
  920.         h = gethostbyname(hname);
  921.         if (h != NULL) {
  922.         bcopy((char *) (h->h_addr), (char *) (&local_site), sizeof(unsigned long));
  923.         local_site_known = 1;
  924.         if (Debug) {
  925.                     fprintf(stderr, "%s: running on host %s (%s)\n", prog,
  926.             inet_ntoa(local_site), hname);
  927.         }
  928.         }
  929.     }
  930.     }
  931.  
  932.     signal(SIGHUP, exiting);          /* Set signal to handle termination */
  933.     signal(SIGINT, exiting);          /* Set signal to handle termination */
  934.     signal(SIGTERM, exiting);          /* Set signal to handle termination */
  935.     signal(SIGALRM, release);          /* Set signal to handle timeout */
  936.     alarm(TockTock);              /* Start periodic timer */
  937.  
  938.     /* Read packets from the sockets. */
  939.  
  940.     while (TRUE) {
  941.     int rll;
  942.     long pkrtime;              /* Time packet received */
  943.     fd_set fdset;
  944.     int wsock, control;
  945.     struct connection *rc = conn;
  946.     char *rchat = NULL;
  947.     int rchatl;
  948.  
  949.     FD_ZERO(&fdset);
  950.     FD_SET(sock, &fdset);
  951.     FD_SET(ssock, &fdset);
  952.     if (select(FD_SETSIZE, &fdset, NULL, NULL, NULL) <= 0) {
  953.         continue;
  954.     }
  955.     wsock = FD_ISSET(sock, &fdset) ? sock :
  956.             (FD_ISSET(ssock, &fdset) ? ssock : -1);
  957.     if (wsock < 0) {
  958.         continue;
  959.     }
  960.     control = wsock == ssock;
  961.     fromlen = sizeof(from);
  962.     if ((rll = recvfrom(wsock, (char *) &sb, sizeof sb, 0, (struct sockaddr *) &from, &fromlen)) < 0) {
  963.         if (errno != EINTR) {
  964.                 perror(!control ? "receiving data packet" :
  965.                                   "receiving control packet");
  966.         }
  967.         continue;
  968.     }
  969.     time(&pkrtime);
  970. #ifdef SHOW_SOCKET
  971.     if (Debug) {
  972.             fprintf(stderr, "%s: %d bytes read from %s socket from %s.\n", prog, rll,
  973.                     control ? "control" : "data", inet_ntoa(from.sin_addr));
  974.     }
  975. #endif
  976.  
  977.     /* See if this connection is active.  If not, initialise a new
  978.        connection. */
  979.  
  980.     newconn = FALSE;
  981.     crit = TRUE;              /* Set connection list critical section lock */
  982.     c = conn;
  983.     while (c != NULL) {
  984.         if (memcmp(&from.sin_addr, &(c->con_addr),
  985.                sizeof(struct in_addr)) == 0) {
  986.         break;
  987.         }
  988.         c = c->con_next;
  989.     }
  990.     if (c == NULL) {
  991.         c = (struct connection *) malloc(sizeof(struct connection));
  992.         if (c != NULL) {
  993.         struct hostent *h;
  994.  
  995.         newconn = TRUE;
  996.         c->con_next = conn;
  997.         conn = c;
  998.         bcopy(&from.sin_addr, &(c->con_addr),
  999.             sizeof(struct in_addr));
  1000.         h = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr),
  1001.                   AF_INET);
  1002.         if (h == NULL) {
  1003.             strcpy(c->con_hostname, inet_ntoa(from.sin_addr));
  1004.         } else {
  1005.             strcpy(c->con_hostname, h->h_name);
  1006.         }
  1007.         }
  1008.     } else if (c->con_timeout == -1) {
  1009.         newconn = TRUE;
  1010.     }
  1011.  
  1012.     /* Initialise fields in connection.  Only fields which need to
  1013.        be reinitialised when a previously idle host resumes activity
  1014.        need be set here. */
  1015.  
  1016.     if (newconn) {
  1017.         c->con_compmodes = NULL;
  1018.         c->con_control = FALSE;
  1019.         c->con_bye = FALSE;
  1020.         c->con_ltime = time(NULL);
  1021.  
  1022.         /* If this is the first connection after a period of
  1023.            inactivity, make sure the timer loop is running at
  1024.            the faster rate we used when one or more connections
  1025.            are active. */
  1026.  
  1027.         if (actives == 0) {
  1028.         alarm(TickTock);
  1029.         }
  1030.     }
  1031.  
  1032.     if (c != NULL) {
  1033.         /* Reset connection timeout. */
  1034.         c->con_timeout = pkrtime;
  1035.         if (newconn || c->con_bye) {
  1036.         if (showhosts) {
  1037.                     fprintf(stderr, "%s: %s %s connect\n", prog, etime(FALSE), c->con_hostname);
  1038.         }
  1039.         c->con_bye = FALSE;
  1040.         }
  1041.     } else {
  1042.         crit = FALSE;
  1043.         if (clash) {
  1044.         release();
  1045.         }
  1046.         continue;
  1047.     }
  1048.  
  1049.     /*  If this is a control channel packet, examine it to
  1050.         determine if this is a new connection, protocol
  1051.         change, end of connection and update the connection
  1052.         list accordingly.  */
  1053.  
  1054.     if (control) {
  1055.         short protocol = PROTOCOL_VATRTP_CRYPT;
  1056.         unsigned char *p = (unsigned char *) &sb;
  1057.         unsigned char *apkt;
  1058.         int proto = (p[0] >> 6) & 3;
  1059.  
  1060.         if (proto == 0) {
  1061.         /* To avoid spoofing by bad encryption keys, require
  1062.                    a proper ID message be seen before we'll flip into
  1063.            VAT protocol. */
  1064.         if (((p[1] == 1) || (p[1] == 3)) ||
  1065.             ((c->con_protocol == PROTOCOL_VAT) && (p[1] == 2))) {
  1066.             protocol = PROTOCOL_VAT;
  1067.             bcopy(p + 2, c->con_session, 2);  /* Save conference ID */
  1068.  
  1069.             if (p[1] == 1) {
  1070.             char uname[256];
  1071.  
  1072.             bcopy(p + 4, uname, rll - 4);
  1073.             uname[rll - 4] = 0;
  1074.             if (strcmp(uname, c->con_uname) != 0) {
  1075.                 strcpy(c->con_uname, uname);
  1076.                 if (showhosts) {
  1077.                                 fprintf(stderr, "%s: %s sending from %s.\n", prog,
  1078.                     c->con_uname, c->con_hostname);
  1079.                 }
  1080.                 changed();
  1081.             }
  1082.             }
  1083.  
  1084.             /* Handling of VAT IDLIST could be a lot more elegant
  1085.                than this. */
  1086.  
  1087.             if (p[1] == 3) {
  1088.             char *uname;
  1089.  
  1090.             uname = (char *) malloc(rll);
  1091.             if (uname != NULL) {
  1092.                 unsigned char *bp = p, *ep = p + rll;
  1093.                 int i = bp[4];
  1094.  
  1095.                 bp += 8;
  1096.                 uname[0] = 0;
  1097.                 *ep = 0;
  1098.                 while (--i >= 0 && bp < ep) {
  1099.                 bp += 4;
  1100.                                 strcat(uname, "\t");
  1101.                 strcat(uname, (char *) bp);
  1102.                 while (isspace(uname[strlen(uname) - 1])) {
  1103.                     uname[strlen(uname) - 1] = 0;
  1104.                 }
  1105.                                 strcat(uname, "\n");
  1106.                 bp += (strlen((char *) bp) + 3) & ~3;
  1107.                 }
  1108.                 if (strncmp(uname, c->con_uname, (sizeof c->con_uname - 1)) != 0) {
  1109.                 strncpy(c->con_uname, uname, sizeof c->con_uname);
  1110.                 if (strlen(uname) > ((sizeof c->con_uname) - 1)) {
  1111.                     c->con_uname[((sizeof c->con_uname) - 1)] = 0;
  1112.                 }
  1113.                 if (showhosts) {
  1114.                                     fprintf(stderr, "%s: now in conference at %s:\n%s", prog,
  1115.                         c->con_hostname, uname);
  1116.                 }
  1117.                 changed();
  1118.                 }
  1119.                 free(uname);
  1120.             }
  1121.             }
  1122.  
  1123.                     /* If it's a DONE packet, reset protocol to unknown. */
  1124.  
  1125.             if (p[1] == 2) {
  1126.             c->con_protocol = protocol = PROTOCOL_UNKNOWN;
  1127.             c->con_timeout = -1;
  1128.             c->con_uname[0] = c->con_email[0] = 0;
  1129.             c->con_bye = TRUE;
  1130.             if (showhosts) {
  1131.                             fprintf(stderr, "%s: %s VAT connection closed.\n",
  1132.                     prog, c->con_hostname);
  1133.             }
  1134.             changed();
  1135.             }
  1136.         }
  1137.         } else if (proto == RTP_VERSION || proto == 1) {
  1138.         if (isValidRTCPpacket((unsigned char *) &sb, rll)) {
  1139.             protocol = (proto == 1) ? PROTOCOL_SPEAKFREE : PROTOCOL_RTP;
  1140.             bcopy(p + 4, c->con_session, 4);  /* Save SSRC */
  1141.             c->con_ltime = time(NULL);
  1142.                     /* If it's a BYE packet, reset protocol to unknown. */
  1143.             if (isRTCPByepacket((unsigned char *) &sb, rll)) {
  1144.             c->con_protocol = protocol = PROTOCOL_UNKNOWN;
  1145.             c->con_timeout = -1;
  1146.             c->con_uname[0] = c->con_email[0] = 0;
  1147.             c->con_bye = TRUE;
  1148.             if (showhosts) {
  1149.                             fprintf(stderr, "%s: %s %s connection closed.\n",
  1150.                     prog, c->con_hostname,
  1151.                                     proto == 1 ? "Speak Freely" : "RTP");
  1152.             }
  1153.             changed();
  1154.  
  1155.                     /* If it's a text chat message, reformat it to
  1156.                be forwarded to all connected hosts. */
  1157.  
  1158.             } else if (isRTCPAPPpacket((unsigned char *) &sb, rll,
  1159.                     RTCP_APP_TEXT_CHAT, &apkt) && apkt != NULL) {
  1160.             char *ident = c->con_hostname,
  1161.                  *echat = NULL;
  1162.  
  1163.             /* To identify the sender, get successively more
  1164.                personal depending on the information we have at
  1165.                hand, working down from hostname (which may just
  1166.                            be an IP address if we couldn't resolve the host,
  1167.                through E-mail address, to user name. */
  1168.  
  1169.             if (c->con_email[0] != 0) {
  1170.                 ident = c->con_email;
  1171.             }
  1172.             if (c->con_uname[0] != 0) {
  1173.                 ident = ident = c->con_uname;
  1174.             }
  1175.  
  1176.             if (Debug) {
  1177.                             printf("%s: Text chat received \"%s: %s\"\n",
  1178.                 c->con_hostname, ident, (char *) (apkt + 12));
  1179.             }
  1180.  
  1181.             echat = malloc(strlen(ident) +
  1182.                        strlen((char *) (apkt + 12)) + 8);
  1183.             if (echat != NULL) {
  1184.                 rchat = malloc(strlen(echat) + 256);
  1185.  
  1186.                 if (rchat != NULL) {
  1187.                                 sprintf(echat, "%s: %s", ident, (char *) (apkt + 12));
  1188.  
  1189.                 rchatl = rtp_make_app(rchat, ssrc, TRUE, RTCP_APP_TEXT_CHAT, echat);
  1190.                 /* Set Speak Freely protocol flag in packet */
  1191.                 rchat[0] = (rchat[0] & 0x3F) | (1 << 6);
  1192.                 }
  1193.                 free(echat);
  1194.             }
  1195.  
  1196.                     /* Otherwise, it's presumably an SDES, from which we
  1197.                should update the user identity information for the
  1198.                connection. */
  1199.  
  1200.             } else {
  1201.             struct rtcp_sdes_request rp;
  1202.  
  1203.             rp.nitems = 5;
  1204.             rp.item[0].r_item = RTCP_SDES_CNAME;
  1205.             rp.item[1].r_item = RTCP_SDES_NAME;
  1206.             rp.item[2].r_item = RTCP_SDES_EMAIL;
  1207.             rp.item[3].r_item = RTCP_SDES_PHONE;
  1208.             rp.item[4].r_item = RTCP_SDES_LOC;
  1209.             if (parseSDES((unsigned char *) &sb, &rp)) {
  1210.                 char cname[256], uname[4096], email[256], phone[256], location[1024];
  1211.  
  1212.                 cname[0] = uname[0] = email[0] = phone[0] = location[0] = 0;
  1213.                 if (rp.item[1].r_text != NULL) {
  1214.                 copySDESitem(rp.item[1].r_text, uname);
  1215.                 if (rp.item[2].r_text != NULL) {
  1216.                     copySDESitem(rp.item[2].r_text, email);
  1217.                 } else if (rp.item[2].r_text != NULL) {
  1218.                     copySDESitem(rp.item[0].r_text, email);
  1219.                 }
  1220.                 } else if (rp.item[2].r_text != NULL) {
  1221.                 copySDESitem(rp.item[2].r_text, uname);
  1222.                 } else if (rp.item[0].r_text != NULL) {
  1223.                 copySDESitem(rp.item[0].r_text, uname);
  1224.                 }
  1225.  
  1226.                 if (rp.item[3].r_text != NULL) {
  1227.                 copySDESitem(rp.item[3].r_text, phone);
  1228.                 }
  1229.                 if (rp.item[4].r_text != NULL) {
  1230.                 copySDESitem(rp.item[4].r_text, location);
  1231.                 }
  1232.                 if (rp.item[0].r_text != NULL) {
  1233.                 copySDESitem(rp.item[0].r_text, cname);
  1234.                 }
  1235.                 if (strcmp(cname, c->con_cname) != 0 ||
  1236.                 strcmp(uname, c->con_uname) != 0 ||
  1237.                 strcmp(email, c->con_email) != 0 ||
  1238.                 strcmp(phone, c->con_phone) != 0 ||
  1239.                 strcmp(location, c->con_loc) != 0
  1240.                 ) {
  1241.                 strcpy(c->con_cname, cname);
  1242.                 strcpy(c->con_uname, uname);
  1243.                 strcpy(c->con_email, email);
  1244.                 strcpy(c->con_phone, phone);
  1245.                 strcpy(c->con_loc, location);
  1246.                 if (uname[0] != 0) {
  1247.                     if (showhosts) {
  1248.                                         fprintf(stderr, "%s: %s", prog, uname);
  1249.                     if (email[0] != 0) {
  1250.                                           fprintf(stderr, " (%s)", email);
  1251.                     }
  1252.                                         fprintf(stderr, " sending from %s.\n",
  1253.                         c->con_hostname);
  1254.                     }
  1255.                     changed();
  1256.                 }
  1257.                 }
  1258.             }
  1259.             }
  1260.         } else {
  1261.             if (Debug) {
  1262.                         fprintf(stderr, "Invalid RTCP packet received.\n");
  1263.             }
  1264.         }
  1265.         } else {
  1266.         if (Debug) {
  1267.                     fprintf(stderr, "Bogus protocol 3 control message.\n");
  1268.         }
  1269.         }
  1270.  
  1271.         /* If protocol changed, update in connection and, if appropriate,
  1272.            update the reply command. */
  1273.  
  1274.         if (protocol != c->con_protocol) {
  1275.         static char *pname[] = {
  1276.                     "Speak Freely",
  1277.                     "VAT",
  1278.                     "RTP",
  1279.                     "VAT/RTP encrypted",
  1280.                     "Unknown"
  1281.         };
  1282.  
  1283.         c->con_protocol = protocol;
  1284.         if (showhosts) {
  1285.                     fprintf(stderr, "%s: %s sending in %s protocol.\n",
  1286.                 prog, c->con_hostname, pname[protocol]);
  1287.         }
  1288.         }
  1289.  
  1290.         /* Done processing control packet.    We never reflect
  1291.            non-chat control packets, just use them to update our own
  1292.            list of connections. */
  1293.  
  1294.         crit = FALSE;
  1295.         if (clash) {
  1296.         release();
  1297.         }
  1298.         if (!rchat) {
  1299.         continue;
  1300.         }
  1301.     }
  1302.     crit = FALSE;
  1303.  
  1304.     /* If this message is tagged with our Speak Freely protocol
  1305.        bit, force protocol back to Speak Freely.  This allows us
  1306.        to switch back to Speak Freely after receiving packets in
  1307.        VAT.  We can still get confused if we receive a packet from
  1308.            an older version of Speak Freely that doesn't tag. */
  1309.  
  1310.     if (c->con_protocol == PROTOCOL_VAT ||
  1311.         c->con_protocol == PROTOCOL_VATRTP_CRYPT) {
  1312.         unsigned char *p = (unsigned char *) &sb;
  1313.  
  1314.         if (((p[0] >> 6) & 3) == 1) {
  1315.         c->con_protocol = PROTOCOL_SPEAKFREE;
  1316.         }
  1317.     }
  1318.  
  1319.     /* If this is not a sound packet (show your face packet,
  1320.        PGP key, etc.) discard it.  These point-to-point facilities
  1321.            won't work and will probably disrupt a conference. */
  1322.  
  1323.     if ((c->con_protocol == PROTOCOL_SPEAKFREE) && (!rchat) &&
  1324.         (!isSoundPacket(ntohl(sb.compression)))) {
  1325.         if (Debug) {
  1326.                 fprintf(stderr, "%s: discarding %d byte control packet (flags 0x%08lX) from %s/%d.\n",
  1327.             prog, rll, (long) ntohl(sb.compression), inet_ntoa(c->con_addr),
  1328.             whichport);
  1329.         }
  1330.         continue;
  1331.     }
  1332.  
  1333.         /*  If we're forwarding a text chat packet, copy it into the
  1334.         buffer which we forward.  */
  1335.  
  1336.     if (rchat) {
  1337.         rll = rchatl;
  1338.         bcopy(rchat, &sb, rll);
  1339.     }
  1340.  
  1341.     /*  This is a data channel packet.  Reflect it back to all
  1342.         active hosts, excepting of course the one which sent
  1343.         it.  Packets are not to sent to hosts which have sent
  1344.         us a BYE packet and not affirmatively re-connected.  */
  1345.  
  1346.     if (Debug) {
  1347.             fprintf(stderr, "%s: reflecting %d bytes from %s/%d (%s).\n",
  1348.         prog, rll, inet_ntoa(c->con_addr), whichport, c->con_hostname);
  1349.     }
  1350.     while (rc != NULL) {
  1351.  
  1352.         /* The test involving local_site in the following statement
  1353.            is to avoid sending a packet to ourselves when the same
  1354.            machine is used to run the reflector and connect to it,
  1355.                using the "monitor site" facility.  In this circumstance
  1356.            there will be a connection in the connection chain for
  1357.            the local copy of sfmike sending to the reflector.  But
  1358.            if we send to this address, what will actually happen is
  1359.            that the reflector (namely us) will receive the packet and,
  1360.            unless it originates from the local machine, re-echo it
  1361.            to all the connected hosts, resulted in stut-stut-stuttering
  1362.                sound.  Since we know that we're in fact listening to
  1363.            whichport on this host, there is no circumstance in which
  1364.            we should ever send a packet on that port to the local host. */
  1365.  
  1366.         if (rc != c && !(rc->con_bye) &&
  1367.         (ntohl(rc->con_addr.s_addr) != INADDR_LOOPBACK) &&
  1368.         (!local_site_known ||
  1369.          (memcmp(&local_site, &(rc->con_addr), sizeof(struct in_addr)) != 0))) {
  1370.         struct sockaddr_in pto;
  1371.  
  1372.         pto.sin_family = AF_INET;
  1373.         pto.sin_port = htons(whichport + (rchat ? 1 : 0));
  1374.         bcopy(&(rc->con_addr), &pto.sin_addr, sizeof(struct in_addr));
  1375.         if (sendto(sock, (char *) &sb, rll,
  1376.             0, (struct sockaddr *) &pto,
  1377.             sizeof(struct sockaddr_in)) < 0) {
  1378.                     perror("reflecting sound packet");
  1379.         }
  1380.         if (Debug) {
  1381.                     fprintf(stderr, "%s: ... reflecting to %s/%d (%s).\n",
  1382.             prog, inet_ntoa(rc->con_addr), whichport + (rchat ? 1 : 0), rc->con_hostname);
  1383.         }
  1384.         }
  1385.         rc = rc->con_next;
  1386.     }
  1387.  
  1388.     /*  If audio monitoring is requested, send the packet to the
  1389.         monitoring host as well.  If the originating site is the
  1390.             same as the monitoring host we don't forward the packet.
  1391.         This case occurs when the same machine is running the
  1392.         reflector and connected to it.  */
  1393.  
  1394.     if (monitor &&
  1395.         (ntohl(c->con_addr.s_addr) != INADDR_LOOPBACK) &&
  1396.         (!local_site_known ||
  1397.          (memcmp(&local_site, &(c->con_addr), sizeof(struct in_addr)) != 0))) {
  1398.         struct sockaddr_in pto;
  1399.  
  1400.         pto.sin_family = AF_INET;
  1401.         pto.sin_port = htons(monitor_port + (rchat ? 1 : 0));
  1402.         bcopy(&monitor_site, &pto.sin_addr, sizeof(struct in_addr));
  1403.         if (sendto(sock, (char *) &sb, rll,
  1404.         0, (struct sockaddr *) &pto,
  1405.         sizeof(struct sockaddr_in)) < 0) {
  1406.                 perror("echoing sound packet to monitor host");
  1407.         }
  1408.         if (Debug) {
  1409.                 fprintf(stderr, "%s: ... sending to monitor host to %s/%d.\n",
  1410.             prog, inet_ntoa(monitor_site), monitor_port + (rchat ? 1 : 0));
  1411.         }
  1412.     }
  1413.  
  1414.     if (rchat) {
  1415.         free(rchat);
  1416.         rchat = NULL;
  1417.     }
  1418.  
  1419.     /*  If verbose mode is selected, indicate any change in
  1420.         protocol or compression mode by this connection.  */
  1421.  
  1422.     c->con_control |= control;
  1423.     if (showhosts && !control) {
  1424.         char *cmodes = compressionType(&sb, c->con_control);
  1425.  
  1426.         if (c->con_compmodes != cmodes) {
  1427.         c->con_compmodes = cmodes;
  1428.                 fprintf(stderr, "%s: %s sending %s.\n", prog, c->con_hostname,
  1429.             cmodes);
  1430.         }
  1431.     }
  1432.  
  1433.     crit = FALSE;
  1434.     if (clash) {
  1435.         release();
  1436.     }
  1437.     }
  1438. #ifdef MEANS_OF_EXIT
  1439.     close(sock);
  1440.     exiting();
  1441.     return 0;
  1442. #endif
  1443. }
  1444.